#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>

#include "ncu_param.h"
#include "ncu_func.h"
#include "ncu_ctrl.h"
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
typedef struct {
	ncu_params nparams;
}ncumsg;

int msg_process(char *msgbuf, int msgsize)
{
	//process
	if (msgsize == sizeof(ncumsg)) {
		ncumsg *msg;
#if 0
		printf("------msg------\n");
		for (i = 0; i < msgsize; i++) {
			printf(" %02hhx", (char)(msgbuf[i]));
			if (0 == (i+1)%16)
				printf("\n");
		}
		printf("\n");
#endif
		msg = (ncumsg*)msgbuf;
#ifndef NCU_DBG_SERVER
		ncu_set_params(&msg->nparams);
		ncu_ctrl_update_param();
#endif
	} else {
		printf("error: msg size error %d, %d\n", msgsize, (int)sizeof(ncu_params));
		return -1;
	}
	return 0;
}

typedef struct {
	char ip[16];
	char port[10];
} ncudbg_thread_param;

static void* ncudbg_thread(void *p)
{
	int  socketfd;
	struct sockaddr_in localaddr;

	ncudbg_thread_param *threadparam = p;
	printf("server: %s-%s\n", threadparam->ip, threadparam->port);

	socketfd = socket (AF_INET, SOCK_DGRAM, 0);
	if (-1 == socketfd) {
		printf("error: socket create err %s\n", strerror(errno));
		return 0;
	}

	//address reuse
	int option = 1;
	setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) );
	memset(&localaddr, 0, sizeof(localaddr));
	localaddr.sin_family = AF_INET;
	localaddr.sin_addr.s_addr = inet_addr(threadparam->ip);
	localaddr.sin_port = htons (atoi(threadparam->port));

	int bindresult = bind(socketfd, (struct sockaddr *) &localaddr, sizeof(localaddr));
	if ( -1 == bindresult ) {
		printf("error: socket bind err %s\n", strerror(errno));
		close(socketfd);
		return 0;
	}
	ssize_t recvsize = 0;
	char *recvbuf = 0;
	ssize_t retsize = 0;
	recvbuf = malloc(64*1024);
	if (NULL == recvbuf) {
		printf("error: malloc err %s\n", strerror(errno));
		return 0;
	}
	recvsize = 64*1024;
	while (1) {
		struct sockaddr_in fromaddr;
		memset((char *)&fromaddr, 0, (int)sizeof(fromaddr));
		socklen_t fromlen = sizeof(fromaddr);

		retsize = recvfrom(socketfd, recvbuf, recvsize, 0, (struct sockaddr *)&fromaddr, &fromlen);
		if (-1 == retsize) {
			printf("error: socket recv err %s\n", strerror(errno));
			continue;
		}
		msg_process(recvbuf, retsize);
	}
	printf("warn: msg recv exit\n");
	free(recvbuf);
	close(socketfd);
	return 0;
}

int ncudbg_server_start(char *ip, char *port)
{
	int ret = -1;
	pthread_t tid;
	ncudbg_thread_param *threadparam;
	threadparam = malloc(sizeof(ncudbg_thread_param));
	if (NULL == threadparam) {
		printf("error: malloc thread param error\n");
		return -1;
	}
	memset(threadparam, 0, sizeof(ncudbg_thread_param));
	memcpy(threadparam->ip, ip, strlen(ip));
	memcpy(threadparam->port, port, strlen(port));

	ret = pthread_create(&tid, NULL, ncudbg_thread, threadparam);
	if (ret) {
		printf("error: pthread_create\n");
		return -1;
	}
	return 0;
}
#ifdef NCU_DBG_SERVER
int main(int argc, char **argv)
{
	printf("server ip: %s\n", argv[1]);
	printf("server port: %s\n", argv[2]);
	printf("\n service starting...\n\n");
	ncudbg_server_start(argv[1], argv[2]);
	sleep(1000);
	return 0;
}
#endif

